using System;
using System.Collections.Generic;
using Game.Framework.Utils;
using UnityEngine;
using UnityEngine.UI;
using Object = UnityEngine.Object;

namespace Game.Framework.UI
{
    public class UIManager
    {
        public static readonly List<string> UI_PREFABPATHS = new List<string>()
        {
            "Assets/AssetsPackage/Bundle",
        };
        
        private UIManager()
        {
        }

        public static UIManager Instance { get; } = new();
        private Transform _rootWidth;
        private Transform _rootHeight;
        private Canvas _canvasWidth;
        private Canvas _canvasHeight;
        internal CanvasScaler _canvasScaler;

        private Dictionary<Type, UIElement> _viewDic;
        private List<UIElement> _viewList;

        public Canvas MRootCanvasWidth => _canvasWidth;
        public Transform MRootWidth => _rootWidth;
        public Camera Camera;
        public float WidthCanvasScale => _canvasWidth.transform.localScale.x;

        public void Init()
        {
            _canvasWidth = GameObject.Find("CanvasWidth").GetComponent<Canvas>();
            _canvasHeight = GameObject.Find("CanvasHeight").GetComponent<Canvas>();
            _rootWidth = _canvasWidth.transform.Find("Root");
            _rootHeight = _canvasHeight.transform.Find("Root");
            Camera = _canvasWidth.transform.Find("UICamera").GetComponent<Camera>();
            _viewDic = new();
            _viewList = new();
            _canvasScaler = _canvasWidth.GetComponent<CanvasScaler>();
        }

        public T Open<T>(string filePath, UIData data = null) where T : UIView, new()
        {
            if (_viewDic.ContainsKey(typeof(T)))
            {
                LogUtil.LogError($"{typeof(T)} 已打开，检查逻辑为何会重复打开");
                return null;
            }

            var prefab = LoadPrefab(filePath);

            if (!prefab)
            {
                LogUtil.LogError($"UI Load Failed:{filePath}");
                return null;
            }

            var ui = new T();
            var root = _rootWidth;
            if (data != null && data.canvasHeight) root = _rootHeight;
            var obj = Object.Instantiate(prefab, root);
            CacheViews(ui);

            ui.Create(obj, data);

            return ui;
        }

        public GameObject LoadPrefab(string filePath)
        {
            GameObject prefab = null;

            foreach (var path in UI_PREFABPATHS)
            {
                var finalPath = $"{path}/{filePath}";
                var info = YooAssetManager.Instance.Package.GetAssetInfo(finalPath);
                if (info != null)
                {
                    if (!string.IsNullOrEmpty(info.AssetPath))
                    {
                        if (Util.IsLE_16_10())
                        {
                            var hander = YooAssetManager.Instance.Package.LoadAssetSync<GameObject>($"{finalPath}_Pad"); 
                            if(hander != null && hander.AssetObject != null)
                                prefab = hander.AssetObject as GameObject;
                        }
            
                        if (!prefab)
                        {
                            var hander = YooAssetManager.Instance.Package.LoadAssetSync<GameObject>($"{finalPath}"); 
                            if(hander != null && hander.AssetObject != null)
                                prefab = hander.AssetObject as GameObject;
                        }
                    }
                }
            }
            
            if (!prefab)
            {
                if (Util.IsLE_16_10())
                {
                    prefab = Resources.Load<GameObject>($"{filePath}_Pad");
                }
            
                if (!prefab) prefab = Resources.Load<GameObject>(filePath);
            }
            return prefab;
        }

        public void Close<T>() where T : UIView
        {
            EventBus.Send(new EVENT_UI_CLOSE(typeof(T)));
        }

        public void Close(UIView view)
        {
            EventBus.Send(new EVENT_UI_CLOSE(view.GetType()));
        }

        // public void CreateDebugMenu<T>() where T : UIElement, new()
        // {
        //     var debug = _canvasWidth.transform.Find("DebugMenu");
        //     if (!debug)
        //     {
        //         var prefab = ResTool.Instance.Load<GameObject>("Debug/Prefabs/DebugMenu");
        //         debug = UnityEngine.Object.Instantiate(prefab, _canvasWidth.transform).transform;
        //         debug.gameObject.name = "DebugMenu";
        //     }
        //
        //     var debugMenu = new T();
        //     debugMenu.Create(debug.gameObject, null);
        //
        //     CacheViews(debugMenu);
        // }

        private void CacheViews<T>(T view) where T : UIElement, new()
        {
            _viewDic.Add(typeof(T), view);
            _viewList.Add(view);
        }

        public void ClearUI(Type viewType)
        {
            if (_viewDic.TryGetValue(viewType, out var view))
            {
                _viewDic.Remove(viewType);
                _viewList.Remove(view);
            }
        }

        public T GetView<T>() where T : UIView
        {
            _viewDic.TryGetValue(typeof(T), out var view);

            return view as T;
        }

        public void FixedUpdate(float deltaTime)
        {
            for (var index = 0; index < _viewList.Count; index++)
            {
                var uiView = _viewList[index];
                uiView.FixedUpdate(deltaTime);
            }
        }

        public bool HasPopup(UIPopupView ignore)
        {
            foreach (var uiElement in _viewList)
            {
                if (uiElement == ignore) continue;

                if (uiElement is UIPopupView) return true;
            }

            return false;
        }

        public void SetUIIndex<T>(int index) where T : UIView
        {
            var ui = UIManager.Instance.GetView<T>();
            if (ui != null)
            {
                ui.Transform.SetSiblingIndex(index);
            }
        }
    }
}